home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSSTER.ASM < prev    next >
Assembly Source File  |  1991-10-24  |  44KB  |  1,477 lines

  1.      NAME    msster
  2. ; File MSSTER.ASM
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Edit history
  9. ; 6 Sept 1991 version 3.11
  10. ; Last edit 6 Sept 1991
  11.  
  12.     public    clscpt, defkey, clscpi, ploghnd, sloghnd, tloghnd
  13.     public  dopar, shokey, cptchr, pktcpt, targ, replay, repflg
  14.     public    kbdflg, shkadr, telnet, ttyact, write, dec2di, caplft
  15.     public    cnvlin, katoi, decout, valout, atoi, cnvstr
  16.     public    pntchr, pntflsh, pntchk, prnhand, prnopen
  17.     public    vfopen, vfread
  18.  
  19. braceop    equ    7bh            ; opening curly brace
  20. bracecl    equ    7dh            ; closing curly brace
  21.  
  22. data     segment
  23.     extrn    flags:byte, trans:byte, diskio:byte, portval:word
  24.     extrn    rdbuf:byte, dosnum:word, filtst:byte, prnname:byte
  25.     extrn    comand:byte, kstatus:word
  26.  
  27. targ    termarg    <0,1,cptchr,0,parnon>
  28. crlf    db      cr,lf,'$'
  29. tmsg1    db    cr,lf,'(Connecting to host, type $' 
  30. tmsg3    db    ' C to return to PC)',cr,lf,cr,lf,cr,lf,'$'
  31. erms21    db    cr,lf,'?Cannot start the connection.$'
  32. erms25    db    cr,lf,'?Input must be numeric$' 
  33. erms22    db    cr,lf,'?No open logging file$'
  34. erms23    db    '*** Error writing session log, suspending capture ***$'
  35. erms24    db    cr,lf,'?Error writing Packet log$'
  36. erms26    db    ' *** PRINTER IS NOT READY ***  press R to retry'
  37.     db    ' or D to discard printing:  $'
  38. esctl    db    'Control-$'
  39. repflg    db    0        ; REPLAY or SET TERM REPLAY filespec flag
  40. rephlp    db    'name of file to playback$'
  41. reperr    db    cr,lf,'?File not found$'    ; for REPLAY command
  42. msgtxt    db    'text to be written$'
  43.  
  44. vfophlp    db    'Filename$'
  45. vfopbad    db    cr,lf,'?Cannot open file $'    ; filename follows
  46. vfclbad    db    cr,lf,'?Cannot close file$'
  47. vfoptwice db    cr,lf,'?File is already open$'
  48. vfnofile db    cr,lf,'?File is not open$'
  49. vfrbad    db    cr,lf,'?Error while reading file$'
  50. vfwbad    db    cr,lf,'?Error while writing file$'
  51. vfrdbad    db    cr,lf,'?more parameters are needed$'
  52. vfrdmsg    db    'name of variable  into which to read a line from file$'
  53. vfrhandle dw    -1            ; READ FILE handle (-1 = invalid)
  54. vfwhandle dw    -1            ; WRITE FILE handle
  55.  
  56. opntab    db    3            ; OPEN FILE table
  57.     mkeyw    'Read',1
  58.     mkeyw    'Write',2
  59.     mkeyw    'Append',3
  60.  
  61. inthlp db cr,lf,'  ?  This message                    F  Dump screen to file'
  62.        db cr,lf,'  C  Close the connection            P  Push to DOS'
  63.        db cr,lf,'  S  Status of the connection        Q  Quit logging'
  64.        db cr,lf,'  M  Toggle mode line                R  Resume logging'
  65.        db cr,lf,'  B  Send a Break                    0  Send a null'
  66.        db cr,lf,'  L  Send a long 1.8 s Break         H  Hangup phone'
  67.        db cr,lf,'  Typing the escape character will send it to the host'
  68.        db 0          ; this short-form obscures less screen area [jrd]
  69.  
  70. intprm    db    'Command> $'
  71. intclet    db    'B','C','F','H','L'    ; single letter commands
  72.     db    'M','P','Q','R','S'    ; must parallel dispatch table intcjmp
  73.     db    '?','0'
  74. numlet    equ    $ - intclet        ; number of entries
  75.     even
  76. intcjmp    dw    intchb,intchc,intchf,intchh,intchl
  77.     dw    intchm,intchp,intchq,intchr,intchs
  78.     dw    intchu,intchn
  79.  
  80. pktbuf    db    cptsiz dup (?)    ; packet logging buffer
  81. pktbp    dw    pktbuf        ; buffer pointer to next free byte
  82. pktlft    dw    cptsiz        ; number free bytes left
  83. capbuf    db    cptsiz dup (?)    ; session logging buffer
  84. capbp    dw    capbuf        ; buffer pointer to next free byte
  85. caplft    dw    cptsiz        ; number free bytes left
  86. prnbuf    db    cptsiz dup (0)    ; printer buffer
  87. pntptr    dw    prnbuf        ; pointer to next free byte
  88. prnhand    dw    4        ; printer file handle (4 = DOS default)
  89. flowon    db    0
  90. flowoff db    0
  91.  
  92.     even
  93. ploghnd    dw    -1        ; packet logging handle
  94. sloghnd    dw    -1        ; session logging handle
  95. tloghnd    dw    -1        ; transaction logging handle
  96.  
  97. clotab    db    6
  98.     mkeyw    'READ-FILE',4001h
  99.     mkeyw    'WRITE-FILE',4002h
  100.     mkeyw    'All-logs',logpkt+logses+logtrn
  101.     mkeyw    'Packets',logpkt
  102.     mkeyw    'Session',logses
  103.     mkeyw    'Transaction',logtrn
  104.  
  105. clseslog db    cr,lf,' Closing Session log$'
  106. clpktlog db    cr,lf,' Closing Packet log$'
  107. cltrnlog db    cr,lf,' Closing Transaction log$'
  108. clohlp    db    cr,lf,' READ-FILE or WRITE-FILE, or the following log files:'
  109.     db    cr,lf,' All-logs, Packets, Session, Transaction$'
  110.  
  111. writetab db    5            ; Write command log file types
  112.     mkeyw    'FILE',4002h        ; FILE
  113.     mkeyw    'Packet',logpkt
  114.     mkeyw    'Screen',80h        ; unused value, to say screen
  115.     mkeyw    'Session',logses
  116.     mkeyw    'Transaction',logtrn
  117.  
  118. sttmsg    db    cr,lf,'Press space to continue ...$'
  119. kbdflg    db    0            ; non-zero means char here from Term
  120. ttyact    db    0            ; Connect mode active, if non-zero
  121. shkadr    dw    0            ; offset of replacement Show Key cmd
  122. ten    dw    10            ; multiplier for setatoi
  123. nbase    dw    10            ; currently active number base
  124. numset    db    '0123456789ABCDEF'    ; number conversion alphabet
  125. temp    dw    0
  126. tmp    db    0
  127. data    ends
  128.  
  129. code    segment
  130.     extrn     comnd:near, outchr:near, stat0:near, iseof:near
  131.     extrn    term:near, strlen:near, pcwait:near, isfile:near
  132.     extrn    beep:near, puthlp:near, getbaud:near, serhng:near
  133.     extrn    serini:near, serrst:near, sendbr:near, putmod:near
  134.     extrn    fpush:near, dumpscr:near, sendbl:near, prtasz:near
  135.     extrn    trnmod:near, dodecom:near
  136.     assume    cs:code, ds:data, es:nothing
  137.  
  138. ; the show key command
  139. shokey    proc    near
  140.     cmp    shkadr,0        ; keyboard translator present?
  141.     je    shokey1            ; e = no, use regular routines
  142.     mov    bx,shkadr        ; get offset of replacement routine
  143.     jmp    bx            ; and execute it rather than us
  144. shokey1:clc
  145.     ret
  146. shokey    endp
  147. ; enter with ax/scan code to define, si/ pointer to definition, cx/ length
  148. ; of definition.  Defines it in definition table. Obsolete.
  149. defkey    proc    near
  150.     ret
  151. defkey    endp
  152.  
  153. ; This is the CONNECT command
  154.  
  155. TELNET     PROC    NEAR
  156.     mov    ah,cmeol
  157.     call    comnd            ; get a confirm
  158.     jnc    teln1            ; nc = success
  159.     ret
  160. teln1:    call    serini            ; ensure port is inited now
  161.     jnc    teln1a            ; nc = success
  162.     test    flags.remflg,dquiet    ; quiet display mode?
  163.     jnz    teln1b            ; nz = yes. Don't write to screen
  164.     mov    dx,offset erms21    ; say cannot start connection
  165.     mov    ah,prstr
  166.     int    dos
  167. teln1b:    or    kstatus,ksgen        ; general command failure
  168.     ret
  169. teln1a:    cmp    flags.vtflg,0        ; emulating a terminal?
  170.     jne    teln2            ; ne= yes, no wait necessary
  171.     mov    ah,prstr
  172.     mov    dx,offset crlf        ; output a crlf
  173.     int    dos
  174.     call    domsg            ; reassure user
  175.     mov    ax,2000            ; two seconds
  176.     call    pcwait            ; pause
  177. teln2:    xor    al,al            ; initial flags
  178.     mov    ttyact,1        ; say telnet is active
  179.     cmp    flags.vtflg,0        ; emulating a terminal?
  180.     je    teln3            ; e = no, say mode line is to be off
  181.     cmp    flags.modflg,0        ; mode line enabled?
  182.     jne    tel010            ; ne = yes
  183. teln3:    or    al,modoff        ; no, make sure it stays off
  184.  
  185. tel010:    test    flags.debug,logses    ; debug mode?
  186.     jz    tel0            ; z = no, keep going
  187.     or    al,trnctl        ; yes, show control chars
  188. tel0:    cmp    flags.vtflg,0        ; emulating a terminal?
  189.     je    tel1            ; e = no
  190.     or    al,emheath        ; say emulating some kind of terminal
  191. tel1:    mov    bx,portval
  192.     cmp    [bx].ecoflg,0        ; echoing?
  193.     jz    tel2
  194.     or    al,lclecho
  195. tel2:    push    ax
  196.     call    getbaud            ; pickup current baud rate for port
  197.     pop    ax
  198.     mov    targ.flgs,al        ; store flags
  199.     mov    ah,flags.comflg        ; COMs port identifier
  200.     mov    targ.prt,ah        ; Port 1 or 2, etc
  201.     mov    ah,[bx].parflg        ; parity flag
  202.     mov    targ.parity,ah
  203.     mov    ax,[bx].baud        ; baud rate identifier
  204.     mov    targ.baudb,al
  205.     xor    ah,ah
  206.     test    flags.capflg,logses    ; select session logging flag bit
  207.     jz    tel3            ; z = no logging
  208.     mov    ah,capt            ; set capture flag
  209. tel3:    or    targ.flgs,ah
  210.     jmp    short tem1
  211.  
  212. TEM:    call    serini            ; init serial port
  213.     jnc    tem1            ; nc = success
  214.     mov    ttyact,0        ; say we are no longer active
  215.     clc
  216.     ret                ; and exit Connect mode
  217.  
  218. tem1:    mov    dx,offset crlf        ; give user an indication that we are
  219.     mov    ah,prstr        ; entering terminal mode
  220.     int    dos
  221.     mov    ax,offset targ        ; point to terminal arguments
  222.     call    term            ; call the main Terminal procedure
  223.     mov    al,kbdflg        ; get the char from Term, if any
  224.     mov    kbdflg,0        ; clear    the flag
  225.     or    al,al            ; was there a char from Term?
  226.     jnz    intch2            ; nz = yes, else ask for one from kbd
  227.  
  228. intchar:call    iseof            ; stdin at eof?
  229.     jnc    intch1            ; nc = not eof, get more
  230.     mov    al,'C'            ; use C when file is empty
  231.     jmp    short intchc        ;  to provide an exit
  232. intch1:    mov    ah,0ch            ; clear Bios keyboard buffer and do
  233.     mov    al,coninq        ;  read keyboard, no echo
  234.     int    dos            ; get a char
  235.     or    al,al            ; scan code indicator?
  236.     jnz    intch2            ; nz = no, ascii
  237.     mov    ah,coninq        ; read and discard scan code
  238.     int    dos
  239.     jmp    short intch1        ; try again
  240. intch2:    mov    flags.cxzflg,0        ; prevent Control-C carryover
  241.     cmp    al,' '            ; space?
  242.     je    tem            ; e = yes, ignore it
  243.     cmp    al,cr            ; check ^M (cr) against plain ascii M
  244.     je    tem            ; exit on cr
  245.     cmp    al,trans.escchr        ; is it the escape char?
  246.     jne    intch3            ; ne = no
  247.     mov    ah,al
  248.     call    outchr
  249.     jmp    short tem        ; return, we are done here
  250. intch3:    push    es
  251.     push    ds
  252.     pop    es
  253.     mov    di,offset intclet    ; command letters
  254.     mov    cx,numlet        ; quantity of them
  255.     cmp    al,' '            ; control code?
  256.     jae    intch3a            ; ae = no
  257.     or    al,40H            ; convert control chars to printable
  258. intch3a:cmp    al,96            ; lower case?
  259.     jb    intch3b            ; b = no
  260.     and    al,not (20h)        ; move to upper case
  261. intch3b:cld
  262.     repne    scasb            ; find the matching letter
  263.     pop    es
  264.     jne    intch4            ; ne = not found, beep and get another
  265.     dec    di            ; back up to letter
  266.     sub    di,offset intclet    ; get letter number
  267.     shl    di,1            ; make it a word index
  268.     jmp    intcjmp[di]        ; dispatch to it
  269. intch4:    call    beep            ; say illegal character
  270.     jmp    intchar
  271.  
  272. intchb:    call    sendbr            ; 'B' send a break
  273.     jmp    tem            ; And return
  274.  
  275. intchc:    mov    ttyact,0        ; 'C' say we are no longer active
  276.     clc                ; and exit Connect mode
  277.     ret
  278.  
  279. intchf:    call    dumpscr            ; 'F' dump screen, use msy routine
  280.     jmp    tem            ; and return
  281.  
  282. intchh:    call    serhng            ; 'H' hangup phone
  283.     call    serrst            ; turn off port
  284.     jmp    tem
  285.  
  286. intchl:    call    sendbl            ; 'L' send a long break
  287.     jmp    tem
  288.  
  289. intchm:    cmp    flags.modflg,1        ; 'M' toggle mode line, enabled?
  290.     jne    intchma            ; ne = no, leave it alone
  291.     xor    targ.flgs,modoff    ; enabled, toggle its state
  292. intchma:jmp    tem            ; and reconnect
  293.  
  294. intchp:    call    fpush            ; 'P' push to DOS
  295.     mov    dx,offset sttmsg    ; say we have returned
  296.     mov    ah,prstr
  297.     int    dos
  298.     jmp    short intchsb        ; wait for a space
  299.  
  300. intchq:    and    targ.flgs,not capt    ; 'Q' suspend session logging
  301.     jmp    tem            ; and resume
  302.  
  303. intchr:    test    flags.capflg,logses    ; 'R' resume logging. Can we capture?
  304.     jz    intchr1            ; z = no
  305.     or    targ.flgs,capt        ; turn on session logging flag
  306. intchr1:jmp    tem            ; and resume
  307.  
  308. intchs:    call    stat0            ; 'S' status, call stat0
  309.     mov    dx,offset sttmsg
  310.     mov    ah,prstr
  311.     int    dos
  312. intchsa:call    iseof            ; is stdin at eof?
  313.     jnc    intchsb            ; nc = not eof, get more
  314.     jmp    tem            ; resume if EOF
  315. intchsb:mov    ah,coninq        ; console input, no echo
  316.     int    dos
  317.     cmp    al,' '            ; space?
  318.     jne    intchsa
  319.     jmp    tem
  320.  
  321. intchu:    mov    ax,offset inthlp    ; '?' get help message
  322.     call    puthlp            ; write help msg
  323.     mov    dx,offset intprm
  324.     mov    ah,prstr        ; Print it
  325.     int    dos
  326.     jmp    intchar            ; Get another char
  327.  
  328. intchn:    xor    ah,ah            ; '0' send a null
  329.     call    outchr
  330.     jmp    tem
  331. TELNET  ENDP
  332.  
  333. ; Reassure user    about connection to the host. Tell him what escape sequence
  334. ; to use to return
  335.  
  336. DOMSG    PROC    NEAR
  337.     mov    ah,prstr
  338.     mov    dx,offset tmsg1
  339.     int    dos
  340.     call    escprt
  341.     mov    ah,prstr
  342.     mov    dx,offset tmsg3
  343.     int    dos
  344.     ret
  345. DOMSG    ENDP
  346.  
  347. ; print    the escape character in readable format.  
  348.  
  349. ESCPRT    PROC    NEAR
  350.     mov    dl,trans.escchr
  351.     cmp    dl,' '
  352.     jge    escpr2
  353.     push    dx
  354.     mov    ah,prstr
  355.     mov    dx,offset esctl
  356.     int    dos
  357.     pop    dx
  358.     add    dl,040H        ; Make it printable
  359. escpr2:    mov    ah,conout
  360.     int    dos
  361.     ret
  362. ESCPRT    ENDP
  363.  
  364.  
  365. ; Set parity for character in Register AL
  366.  
  367. dopar:    push    bx
  368.     mov    bx,portval
  369.     mov    bl,[bx].parflg        ; get parity flag byte
  370.     cmp    bl,parnon        ; No parity?
  371.     je    parret            ; Just return
  372.     and    al,07FH            ; Strip parity. Same as Space parity
  373.     cmp    bl,parspc        ; Space parity?
  374.     je    parret            ; e = yes, then we are done here
  375.     cmp    bl,parevn        ; Even parity?
  376.     jne    dopar0            ; ne = no
  377.     or    al,al
  378.     jpe    parret            ; pe = even parity now
  379.     xor    al,080H            ; Make it even parity
  380.     jmp    short parret
  381. dopar0:    cmp    bl,parmrk        ; Mark parity?
  382.     jne    dopar1            ; ne = no
  383.     or    al,080H            ; Turn on the parity bit
  384.     jmp    short parret
  385. dopar1:    cmp    bl,parodd        ; Odd parity?    
  386.     or    al,al
  387.     jpo    parret            ; Already odd, leave it
  388.     xor    al,080H            ; Make it odd parity
  389. parret:    pop    bx
  390.     ret
  391.  
  392. ; REPLAY filespec  through terminal emulator
  393. replay    proc    near
  394.     mov    dx,offset rdbuf        ; place for filename
  395.     mov    bx,offset rephlp    ; help
  396.     mov    repflg,0        ; clear the replay active flag
  397.     mov    ah,cmword        ; get filename
  398.     call    comnd
  399.     jc    replay2            ; c = failure
  400.     mov    ah,cmeol        ; get an EOL confirm
  401.     call    comnd
  402.     jc    replay2            ; c = failure
  403.     mov    ah,open2        ; open file
  404.     xor    al,al            ; open readonly
  405.     cmp    byte ptr dosnum+1,2    ; above DOS 2?
  406.     jna    replay1            ; na = no, so no shared access
  407.     mov    al,0+40h        ; open readonly, deny none
  408. replay1:mov    dx,offset rdbuf        ; asciiz filename
  409.     int    dos
  410.     jnc    replay3            ; nc = success
  411.     mov    ah,prstr
  412.     mov    dx,offset reperr    ; Cannot open that file
  413.     int    dos
  414.     clc
  415. replay2:ret
  416. replay3:mov    diskio.handle,ax    ; file handle
  417.     mov    repflg,1        ; set replay flag
  418.     call    telnet            ; enter Connect mode
  419.     mov    bx,diskio.handle
  420.     mov    ah,close2        ; close the file
  421.     int    dos
  422.     mov    repflg,0        ; clear the flag
  423.     clc
  424.     ret
  425. replay    endp
  426.  
  427. cptchr    proc    near            ; session capture routine, char in al
  428.     test    flags.capflg,logses    ; session logging active now?
  429.     jz    cptch1            ; z = no
  430.     push    di
  431.     mov    di,capbp        ; buffer pointer
  432.     mov    byte ptr [di],al
  433.     inc    capbp
  434.     pop    di
  435.     dec    caplft            ; decrement chars remaining
  436.     jg    cptch1            ; more room, forget this part
  437.     call    cptdmp            ; dump the info
  438. cptch1:    ret
  439. cptchr    endp
  440.  
  441. cptdmp    proc    near            ; empty the capture buffer
  442.     push    ax
  443.     push    bx
  444.     push    cx
  445.     push    dx
  446.     mov    bx,sloghnd        ; get file handle
  447.     or    bx,bx            ; is file open?
  448.     jle    cptdm1            ; le = no, skip it
  449.     mov    cx,cptsiz        ; original buffer size
  450.     sub    cx,caplft        ; minus number remaining
  451.     jl    cptdm2            ; means error
  452.     jcxz    cptdm1            ; z = nothing to do
  453.     mov    dx,offset capbuf    ; the capture routine buffer
  454.     mov    ah,write2        ; write with filehandle
  455.     int    dos            ; write out the block
  456.     jc    cptdm2            ; carry set means error
  457.     cmp    ax,cx            ; wrote all?
  458.     jne    cptdm2            ; no, an error
  459.     mov    capbp,offset capbuf
  460.     mov    caplft,cptsiz        ; init buffer ptr & chrs left
  461.     clc
  462.     jmp    short cptdm1
  463. cptdm2:    and    targ.flgs,not capt    ; so please stop capturing
  464.     mov    dx,offset erms23    ; tell user the bad news
  465.     call    putmod            ; write on mode line
  466.     stc
  467. cptdm1:    pop    dx
  468.     pop    cx
  469.     pop    bx
  470.     pop    ax
  471.     ret
  472. cptdmp    endp
  473.  
  474. pktcpt    proc    near            ; packet log routine, char in al
  475.     test    flags.capflg,logpkt    ; logging packets now?
  476.     jz    pktcp1            ; z = no
  477.     push    di
  478.     mov    di,pktbp        ; buffer pointer
  479.     mov    [di],al            ; store char in buffer
  480.     inc    pktbp            ; move pointer to next free byte
  481.     pop    di
  482.     dec    pktlft            ; decrement chars remaining
  483.     jg    pktcp1            ; g = more room, forget this part
  484.     call    pktdmp            ; dump the info
  485. pktcp1:    ret
  486. pktcpt    endp
  487.  
  488. pktdmp    proc    near            ; empty the capture buffer
  489.     push    ax
  490.     push    bx
  491.     push    cx
  492.     push    dx
  493.     mov    bx,ploghnd        ; get file handle
  494.     or    bx,bx            ; is file open?
  495.     jle    cptdm1            ; le = no, skip it
  496.     mov    cx,cptsiz        ; original buffer size
  497.     sub    cx,pktlft        ; minus number remaining
  498.     jl    pktdm2            ; l means error
  499.     jcxz    pktdm1            ; z = nothing to do
  500.     mov    dx,offset pktbuf    ; the capture routine buffer
  501.     mov    ah,write2        ; write with filehandle
  502.     int    dos            ; write out the block
  503.     jc    pktdm2            ; carry set means error
  504.     cmp    ax,cx            ; wrote all?
  505.     jne    pktdm2            ; ne = no, error
  506.     mov    pktbp,offset pktbuf
  507.     mov    pktlft,cptsiz        ; init buffer ptr & chrs left
  508.     jmp    short pktdm1
  509. pktdm2:    and    flags.capflg,not logpkt    ; so please stop capturing
  510.     mov    dx,offset erms24    ; tell user the bad news
  511.     mov    ah,prstr
  512.     int    dos
  513.     call    clscp4            ; close the packet log
  514. pktdm1:    pop    dx
  515.     pop    cx
  516.     pop    bx
  517.     pop    ax
  518.     ret
  519. pktdmp    endp
  520.  
  521. ; CLOSE command
  522.  
  523. clscpt    proc    near
  524.     mov    ah,cmkey        ; get kind of file to close
  525.     mov    dx,offset clotab    ; close table
  526.     mov    bx,offset clohlp    ; help
  527.     call    comnd
  528.            jc    clscp2            ; c = failure
  529.     mov    temp,bx
  530.     mov    ah,cmeol
  531.     call    comnd
  532.            jc    clscp2            ; c = failure
  533.     mov    kstatus,kssuc        ; success status thus far
  534.     mov    bx,temp
  535.     cmp    bh,40h            ; READ-FILE or WRITE-FILE?
  536.     jne    clscp0            ; ne = no
  537.     mov    ax,bx
  538.     jmp    vfclose            ; close FILE, pass kind in AX
  539. clscp0:    test    flags.capflg,0FFH    ; are any kinds active?
  540.     jz    clscp1            ; z = no
  541.            cmp    bx,logpkt+logses+logtrn    ; close all?
  542.     je    clscpi            ; e = yes
  543.     cmp    bx,logpkt        ; just packet?
  544.     je    clscp4
  545.     cmp    bx,logses        ; just session?
  546.     je    clscp6
  547.     cmp    bx,logtrn        ; just session?
  548.     jne    clscp1            ; ne = no
  549.     jmp    clscp8
  550. clscp1:    mov    dx,offset erms22    ; say none active
  551.     mov    ah,prstr
  552.     int    dos
  553.     clc
  554.     ret
  555. clscp2:    mov    kstatus,ksgen        ; general cmd failure status
  556.     stc
  557.     ret
  558.                     ; CLSCPI called at Kermit exit
  559. CLSCPI:    mov    bx,portval
  560.     mov    [bx].flowc,0        ; set no flow control so no sending it
  561.     call    pntflsh            ; flush PRN buffer
  562.     call    clscp4            ; close packet log
  563.     call    clscp6            ; close session log
  564.     call    clscp8            ; close transaction log
  565.     mov    al,2            ; close WRITE FILE log
  566.     call    vfclose
  567.     clc                ; return success
  568.     ret
  569.  
  570. clscp4:    push    bx            ; PACKET LOG
  571.     mov    bx,ploghnd        ; packet log handle
  572.     or    bx,bx            ; is it open?
  573.     jle    clscp5            ; e = no
  574.     call    pktdmp            ; dump buffer
  575.     cmp    flags.takflg,0        ; ok to echo?
  576.     je    clscp5            ; e = no
  577.     mov    ah,close2
  578.     int    dos
  579.     mov    ah,prstr
  580.     mov    dx,offset clpktlog    ; tell what we are doing
  581.     int    dos
  582. clscp5:    mov    ploghnd,-1        ; say handle is invalid
  583.     pop    bx
  584.     and    flags.capflg,not logpkt    ; say this log is closed
  585.     ret
  586.  
  587. clscp6:    push    bx            ; SESSION LOG
  588.     mov    bx,sloghnd        ; session log handle
  589.     or    bx,bx            ; is it open?
  590.     jle    clscp7            ; e = no
  591.     call    cptdmp            ; dump buffer
  592.     cmp    flags.takflg,0        ; ok to echo?
  593.     je    clscp7            ; e = no
  594.     mov    ah,close2
  595.     int    dos
  596.     mov    ah,prstr
  597.     mov    dx,offset clseslog    ; tell what we are doing
  598.     int    dos
  599. clscp7:    mov    sloghnd,-1        ; say handle is invalid
  600.     pop    bx
  601.     and    flags.capflg,not logses    ; say this log is closed
  602.     ret
  603.  
  604. clscp8:    push    bx            ; TRANSACTION LOG
  605.     mov    bx,tloghnd        ; transaction log handle
  606.     or    bx,bx            ; is it open?
  607.     jle    clscp9            ; e = no
  608.     cmp    flags.takflg,0        ; ok to echo?
  609.     je    clscp9            ; e = no
  610.     mov    ah,close2
  611.     int    dos
  612.     mov    ah,prstr
  613.     mov    dx,offset cltrnlog    ; tell what we are doing
  614.     int    dos
  615. clscp9:    mov    tloghnd,-1        ; say handle is invalid
  616.     pop    bx
  617.     and    flags.capflg,not logtrn    ; say this log is closed
  618.     ret
  619. clscpt    endp
  620.  
  621. ; Print on PRN the char in register al. On success return with C bit clear.
  622. ; On failure do procedure pntchk and return its C bit (typically C set).
  623. ; Uses buffer dumpbuf (screen dump).
  624. pntchr    proc    near
  625.     cmp    pntptr,offset prnbuf+cptsiz ; buffer full yet?
  626.     jb    pntchr1            ; b = no
  627.     call    pntflsh            ; flush buffer now
  628.     jnc    pntchr1            ; nc = success
  629.     ret                ; c = fail, discard char
  630. pntchr1:push    bx
  631.     mov    bx,pntptr        ; pointer to next open slot
  632.     mov    [bx],al            ; store the character
  633.     inc    bx            ; update pointer
  634.     mov    pntptr,bx        ; save pointer
  635.     pop    bx
  636.     clc                ; clear carry bit
  637.     ret
  638. pntchr    endp
  639.  
  640. ; Flush printer buffer. Return carry clear if success.
  641. ; On failure do procedure pntchk and return its C bit (typically C set).
  642. ; Uses buffer dumpbuf (screen dump).
  643. pntflsh    proc    near
  644.     cmp    pntptr,offset prnbuf    ; any text in buffer?
  645.     ja    pntfls1            ; a = yes
  646.     clc
  647.     ret                ; else nothing to do
  648. pntfls1:cmp    prnhand,0        ; is printer handle valid?
  649.     jg    pntfls2            ; g = yes
  650.     mov    pntptr,offset prnbuf
  651.     clc                ; omit printing, quietly
  652.     ret
  653. pntfls2:push    ax
  654.     push    bx
  655.     push    cx
  656.     push    dx
  657.     push    si
  658.     push    di
  659.     push    es
  660.     mov    bx,portval
  661.     mov    ax,[bx].flowc        ; get flow control chars (al=xoff)
  662.     mov    flowon,ah
  663.     mov    flowoff,al        ; save for later
  664.     xchg    ah,al            ; get flow control char
  665.     or    ah,ah            ; flow control active?
  666.     jz    pntfls3            ; z = no, not using xoff
  667.     call    outchr            ; output xoff (ah), no echo
  668. pntfls3:mov    bx,prnhand        ; file handle for DOS printer PRN
  669.     mov    dx,offset prnbuf    ; start of buffer
  670.     mov    cx,pntptr
  671.     sub    cx,dx            ; cx = current byte count
  672. pntfls4:push    cx
  673.     push    dx
  674.     mov    cx,1
  675.     mov    bx,prnhand
  676.     mov    ah,write2
  677.     int    dos            ; write buffer to printer
  678.     pop    dx
  679.     pop    cx
  680.     jc    pntfls5            ; c = call failed
  681.     cmp    ax,1            ; did we write it?
  682.     jne    pntfls5            ; ne = no, dos critical error
  683.     inc    dx            ; point to next char
  684.     loop    pntfls4
  685.     mov    pntptr,offset prnbuf    ; reset buffer pointer
  686.     clc                ; declare success
  687.     jmp    pntfls11
  688. pntfls5:mov    si,dx            ; address of next char to be printed
  689.     mov    di,offset prnbuf    ; start of buffer
  690.     sub    dx,di            ; dx now = number successful prints
  691.     mov    cx,pntptr
  692.     sub    cx,si            ; count of chars to be printed
  693.     jle    pntfls6
  694.     mov    ax,ds
  695.     mov    es,ax
  696.     cld
  697.     rep    movsb            ; copy unwritten to start of buffer
  698. pntfls6:sub    pntptr,dx        ; move back printer pointer by ok's
  699. pntfls7:mov    dx,offset erms26    ; printer not ready, get user action
  700.     call    putmod            ; write new mode line
  701.     call    beep            ; make a noise
  702.     mov    ah,0ch            ; clear DOS typeahead buffer
  703.     mov    al,1            ; read from DOS buffer
  704.     int    dos
  705.     or    al,al            ; Special key?
  706.     jnz    pntfls8            ; nz = no, consume
  707.     mov    al,1            ; consume scan code
  708.     int    dos
  709.     jmp    short pntfls7        ; try again
  710.  
  711. pntfls8:and    al,not 20h        ; lower to upper case quickie
  712.     cmp    al,'R'            ; Retry?
  713.     jne    pntfls8a        ; ne = no
  714.     call    trnmod            ; toggle mode line
  715.     call    trnmod            ; back to same state as before
  716.     jmp    pntfls3            ; go retry
  717. pntfls8a:cmp    al,'D'            ; Discard printing?
  718.     jne    pntfls7            ; ne = no, try again
  719.     mov    bx,prnhand
  720.     cmp    bx,4            ; stdin/stdout/stderr/stdaux/stdprn?
  721.     jbe    pntfls9            ; be = yes, always available
  722.     mov    ah,close2        ; close this file
  723.     int    dos
  724. pntfls9:mov    bx,offset prnname    ; name of printer file
  725.     mov    word ptr [bx],'UN'    ; set to NUL<0>
  726.     mov    word ptr [bx+2],'L'+0
  727.     mov    pntptr,offset prnbuf    ; reset pointer
  728.     mov    prnhand,-1        ; declare handle invalid
  729. pntfls10:call    trnmod            ; toggle mode line
  730.     call    trnmod            ; back to same state as before
  731.     stc                ; declare failure
  732. pntfls11:pushf
  733.     mov    ah,flowon
  734.     or    ah,ah            ; flow control active?
  735.     jz    pntfls12        ; z = no, not using xon
  736.     call    outchr            ; output xon (al), no echo
  737. pntfls12:popf
  738.     pop    es
  739.     pop    di
  740.     pop    si
  741.     pop    dx
  742.     pop    cx
  743.     pop    bx
  744.     pop    ax
  745.     ret                ; nc = success
  746. pntflsh    endp
  747.  
  748. ; Check for PRN (DOS's printer) being ready. If ready, return with C clear
  749. ; Otherwise, write Not Ready msg on mode line and return with C bit set.
  750. ; N.B. DOS Critical Error will occur here if PRN is not ready.  [jrd]
  751. pntchk    proc    near
  752.     push    dx
  753.     push    cx
  754.     push    ax
  755.     mov    cx,10            ; ten retries before declaring error
  756.     cmp    prnhand,0        ; printer handle valid?
  757.     jle    pntchk2            ; le = no, invalid
  758. pntchk0:push    bx
  759.     mov    bx,prnhand        ; file handle
  760.     mov    ah,ioctl        ; get printer status, via DOS
  761.     mov    al,7            ; status for output
  762.     int    dos
  763.     pop    bx
  764.     jc    pntchk1            ; c = call failed
  765.     cmp    al,0ffh            ; code for Ready?
  766.     je    pntchk3            ; e = yes, assume printer is ready
  767. pntchk1:push    cx            ; save counter, just in case
  768.     mov    ax,100            ; wait 100 millisec
  769.     call    pcwait
  770.     pop    cx
  771.     loop    pntchk0            ; and try a few more times
  772.                     ; get here when printer is not ready
  773. pntchk2:pop    ax
  774.     pop    cx
  775.     pop    dx
  776.     stc                ; say printer not ready
  777.     ret
  778. pntchk3:pop    ax
  779.     pop    cx
  780.     pop    dx
  781.     clc                ; say printer is ready
  782.     ret
  783. pntchk    endp
  784.  
  785.  
  786. prnopen    proc    near
  787.     push    ax
  788.     push    bx
  789.     push    cx
  790.     push    dx
  791.     mov    prnhand,4        ; preset default handle
  792.     mov    dx,offset prnname    ; name of disk file, from mssset
  793.     mov    ax,dx            ; where isfile wants name ptr
  794.     call    isfile            ; what kind of file is this?
  795.     jc    prnop3            ; c = no such file, create it
  796.     test    byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
  797.     jnz    prnop2            ; nz = no
  798.     mov    al,1            ; writing
  799.     mov    ah,open2        ; open existing file
  800.     int    dos
  801.     jc    prnop2            ; c = failure
  802.     mov    prnhand,ax        ; save file handle
  803.     mov    bx,ax            ; need handle here
  804.     mov    cx,0ffffh        ; setup file pointer
  805.     mov    dx,-1            ; and offset
  806.     mov    al,2            ; move to eof minus one byte
  807.     mov    ah,lseek        ; seek the end
  808.     int    dos
  809.     pop    dx
  810.     pop    cx
  811.     pop    bx
  812.     pop    ax
  813.     clc
  814.     ret
  815. prnop2:    stc
  816.     ret
  817. prnop3:    test    filtst.fstat,80h    ; access problem?
  818.     jnz    prnop2            ; nz = yes
  819.     mov    ah,creat2        ; file did not exist
  820.     mov    cx,20h            ; attributes, archive bit
  821.     int    dos
  822.     mov    prnhand,ax        ; save file handle
  823.     pop    dx
  824.     pop    cx
  825.     pop    bx
  826.     pop    ax
  827.     ret                ; may have carry set
  828. prnopen    endp
  829.  
  830. ; worker: copy line from si to di, first removing trailing spaces, second
  831. ; parsing out curly braced strings, then third converting \{b##} in strings
  832. ; to binary numbers. Returns carry set if error; else carry clear, with byte
  833. ; count in cx. Braces are optional but must occur in pairs.
  834. ; Items which cannot be converted to legal numbers are copied verbatium
  835. ; to the output string (ex: \{c}  is copied as \{c}  but \{x0d} is hex 0dh).
  836. cnvlin    proc    near
  837.     push    ax
  838.     push    si            ; source ptr
  839.     push    di            ; destination ptr
  840.     push    es            ; end of save regs
  841.     push    ds            ; move ds into es
  842.     pop    es            ; use data segment for es:di
  843.     call    cnvstr            ; trim trailing, parse curly braces
  844.     xor    cx,cx            ; initialize returned byte count
  845. cnvln1:    cmp    byte ptr [si],0        ; at end of string?
  846.     je    cnvln2            ; e = yes, exit
  847.     call    katoi            ; read char, convert ascii to binary
  848.     cld
  849.     stosb                ; save the char
  850.     inc    cx            ; and count it
  851.     or    ah,ah            ; is returned number > 255?
  852.     jz    cnvln1            ; z = no, do more chars
  853.     push    ax
  854.     stosb                ; save high order byte next
  855.     pop    ax
  856.     inc    cx
  857.     jmp    short cnvln1        ; do more chars
  858. cnvln2:    mov    byte ptr [di],0        ; plant terminator
  859.     clc                ; clear c bit, success
  860.     pop    es            ; restore regs
  861.     pop    di            ; destination ptr
  862.     pop    si            ; source ptr
  863.     pop    ax
  864.     ret
  865. cnvlin    endp
  866.  
  867. ; Convert string by first remove trailing spaces and then removing surrounding
  868. ; curly brace delimiter pair. Converts text in place.
  869. ; Enter with source ptr in si.
  870. ; Preserves all registers, uses byte tmp. 9 Oct 1987 [jrd]
  871. cnvstr    proc    near
  872.     push    ax
  873.     push    cx
  874.     push    dx
  875.     push    si            ; save start of source string
  876.     push    di
  877.     push    es
  878.                     ; 1. Trim trailing spaces
  879.     mov    dx,si            ; source address
  880.     call    strlen            ; get current length to cx
  881.     jcxz    cnvst4            ; z = nothing there
  882.     mov    di,si            ; set di to source address
  883.     add    di,cx            ; start at end of string
  884.     dec    di            ; ignore terminator
  885.     mov    al,spc            ; scan while spaces
  886.     push    ds
  887.     pop    es            ; set es to data segment
  888.     std                ; search backward
  889.     repe    scasb            ; scan off trailing spaces
  890.     mov    byte ptr [di+2],0    ; terminate string after last text
  891.     cld
  892.     mov    di,si            ; set destination address to source
  893.                     ; 2. Parse off curly brace delimiters
  894.     cmp    byte ptr [si],braceop    ; opening brace?
  895.     jne    cnvst4            ; ne = no, ignore brace-matching code
  896.     inc    si            ; skip opening brace
  897.     mov    dl,braceop        ; opening brace (we count them up)
  898.     mov    dh,bracecl        ; closing brace (we count them down)
  899.     mov    tmp,1            ; we are at brace level 1
  900. cnvst1:    cld                ; search forward
  901.     lodsb                ; read a string char
  902.     stosb                ; store char (skips opening brace)
  903.     or    al,al            ; at end of string?
  904.     jz    cnvst4            ; z = yes, we are done
  905.     cmp    al,dl            ; an opening brace?
  906.     jne    cnvst2            ; ne = no
  907.     inc    tmp            ; yes, increment brace level
  908.     jmp    short cnvst1        ;  and continue scanning
  909.  
  910. cnvst2:    cmp    al,dh            ; closing brace?
  911.     jne    cnvst1            ; ne = no, continue scanning
  912.     dec    tmp            ; yes, decrement brace level
  913.     cmp    byte ptr [si],0        ; have we just read the last char?
  914.     jne    cnvst3            ; no, continue scanning
  915.     mov    tmp,0            ; yes, this is the closing brace
  916. cnvst3:    cmp    tmp,0            ; at level 0?
  917.     jne    cnvst1            ; ne = no, #opening > #closing braces
  918.     mov    byte ptr [di-1],0    ; plant terminator on closing brace
  919.  
  920. cnvst4:    pop    es            ; recover original registers
  921.     pop    di
  922.     pop    si
  923.     pop    dx
  924.     pop    cx
  925.     pop    ax
  926.     ret
  927. cnvstr    endp
  928.  
  929. ; Convert ascii strings of the form "\{bnnn}" to a binary word in ax.
  930. ; The braces are optional but must occur in pairs. Numeric base indicator "b"
  931. ; is O or o or X or x or D or d or missing, for octal, hex, or decimal (def).
  932. ; Enter with si pointing at "\".
  933. ; Returns binary value in ax with carry clear and si to right of "}" or at
  934. ; terminating non-numeric char if successful; otherwise, a failure,
  935. ; return carry set with si = entry value + 1 and first read char in al.
  936.  
  937. katoi    proc    near
  938.     cld
  939.     lodsb                ; get first char
  940.     xor    ah,ah            ; clear high order field
  941.     push    cx            ; save working reg
  942.     push    si            ; save entry si+1
  943.     push    bx
  944.     push    ax            ; save read char
  945.     or    al,al            ; end of text?
  946.     jz    katoi1a            ; z = yes, exit failure
  947.     cmp    al,'\'            ; escape char?
  948.     je    katoi1b            ; e = yes
  949. katoi1a:jmp    katoix            ; common jump point to exit failure
  950. katoi1b:lodsb                ; get next char, maybe brace
  951.     or    al,al            ; premature end?
  952.     jz    katoi1a            ; z = yes, exit failure
  953.     xor    bx,bx            ; no conv yet, assume no opening brace
  954.     cmp    al,braceop        ; opening brace?
  955.     jne    katoi2            ; ne = no, have number or base
  956.     mov    bl,bracecl        ; remember a closing brace is needed
  957.     lodsb                ; get number base, if any
  958. katoi2:    xor    cx,cx            ; temporary place for binary value
  959.     mov    nbase,10        ; assume decimal numbers
  960.     or    al,al            ; premature end?
  961.     jz    katoix            ; z = yes, exit failure
  962.     cmp    al,'a'            ; lower case?
  963.     jb    katoi3            ; b = no
  964.     cmp    al,'z'            ; in range of lower case?
  965.     ja    katoi3            ; a = no
  966.     and    al,5fh            ; map to upper case
  967. katoi3:    cmp    al,'O'            ; octal?
  968.     jne    katoi4            ; ne = no
  969.     mov    nbase,8            ; set number base
  970.     jmp    short katoi6
  971. katoi4:    cmp    al,'X'            ; hex?
  972.     jne    katoi5            ; ne = no
  973.     mov    nbase,16
  974.     jmp    short katoi6
  975. katoi5:    cmp    al,'D'            ; decimal?
  976.     jne    katoi7            ; ne = no base char, assume decimal
  977.     mov    nbase,10
  978. katoi6:    lodsb                ; get a digit
  979. katoi7:    or    al,al            ; premature end?
  980.     jz    katoi8a            ; z = yes, use it as a normal end
  981.     cmp    al,bl            ; closing brace?
  982.     je    katoi9            ; e = yes
  983.     call    cnvdig            ; convert ascii to binary digit
  984.     jc    katoi8            ; c = cannot convert
  985.     inc    bh            ; say we did a successful conversion
  986.     xor    ah,ah            ; clear high order value
  987.     push    ax            ; save this byte's value
  988.     xchg    ax,cx            ; put binary summation in ax
  989.     mul    nbase            ; scale up current sum
  990.     xchg    ax,cx            ; put binary back in cx
  991.     pop    ax            ; recover binary digit
  992.     add    cx,ax            ; form running sum
  993.     jc    katoix            ; c = overflow error, exit
  994.     or    dx,dx            ; overflow?
  995.     jnz    katoix            ; nz = yes, exit with error
  996.     jmp    short katoi6        ; get more
  997.  
  998. katoi8:    or    bl,bl            ; closing brace needed?
  999.     jnz    katoix            ; nz = yes, but not found
  1000. katoi8a:dec    si            ; backup to reread terminator
  1001. katoi9:    or    bh,bh            ; did we do any conversion?
  1002.     jz    katoix            ; z = no, exit failure
  1003.     pop    ax            ; throw away old saved ax
  1004.     pop    bx            ; restore bx
  1005.     pop    ax            ; throw away starting si, keep current
  1006.     mov    ax,cx            ; return final value in ax
  1007.     pop    cx            ; restore old cx
  1008.     clc                ; clear carry for success
  1009.     ret
  1010. katoix:    pop    ax            ; restore first read al
  1011.     pop    bx
  1012.     pop    si            ; restore start value + 1
  1013.     pop    cx            ; restore old cx
  1014.     stc                ; set carry for failure
  1015.     ret
  1016. katoi    endp
  1017.  
  1018. cnvdig    proc    near            ; convert ascii code in al to binary
  1019.     push    cx            ; return carry set if cannot
  1020.     push    es            ; nbase has numeric base
  1021.     push    di
  1022.     push    ax
  1023.     cmp    al,'a'            ; lower case?
  1024.     jb    cnvdig1            ; b = no
  1025.     cmp    al,'f'            ; highest hex digit
  1026.     ja    cnvdigx            ; a = illegal symbol
  1027.     sub    al,'a'-'A'        ; convert 'a' to 'f' to upper case
  1028. cnvdig1:mov    di,offset numset    ; set of legal number symbols
  1029.     mov    cx,nbase        ; number of legal symbols in this base
  1030.     cmp    cx,cx            ; preset z flag
  1031.     push    ds
  1032.     pop    es            ; point es at data segment
  1033.     cld                ; scan forward
  1034.     repne    scasb            ; find character in set
  1035.     jne    cnvdigx            ; ne = not found
  1036.     inc    cx            ; offset auto-dec of repne scasb above
  1037.     sub    cx,nbase        ; counted off minus length
  1038.     neg    cx            ; two's complement = final value
  1039.     pop    ax            ; saved ax
  1040.     mov    ax,cx            ; return binary in al
  1041.     clc                ; c clear for success
  1042.     jmp    short cnvdixx        ; exit
  1043. cnvdigx:stc                ; c set for failure
  1044.     pop    ax
  1045. cnvdixx:pop    di
  1046.     pop    es
  1047.     pop    cx
  1048.     ret
  1049. cnvdig    endp    
  1050.  
  1051. decout    proc    near        ; display decimal number in ax
  1052.     push    ax
  1053.     push    cx
  1054.     push    dx
  1055.     mov    cx,10        ; set the numeric base
  1056.     call    valout        ; convert and output value
  1057.     pop    dx
  1058.     pop    cx
  1059.     pop    ax
  1060.     ret
  1061. decout    endp
  1062.  
  1063. valout    proc    near        ; output number in ax using base in cx
  1064.                 ; corrupts ax and dx
  1065.     xor    dx,dx        ; clear high word of numerator
  1066.     div    cx        ; (ax / cx), remainder = dx, quotient = ax
  1067.     push    dx        ; save remainder for outputting later
  1068.     or    ax,ax        ; any quotient left?
  1069.     jz    valout1        ; z = no
  1070.     call    valout        ; yes, recurse
  1071. valout1:pop    dx        ; get remainder
  1072.     add    dl,'0'        ; make digit printable
  1073.     cmp    dl,'9'        ; above 9?
  1074.     jbe    valout2        ; be = no
  1075.     add    dl,'A'-1-'9'    ; use 'A'--'F' for values above 9
  1076. valout2:mov    ah,conout
  1077.     int    dos
  1078.     ret
  1079. valout    endp
  1080.  
  1081. ; Convert input in buffer pointed to by SI to real number which is returned
  1082. ; in AX.  Enter with string size in AH.
  1083. ; Return carry set on failure, carry clear on success.
  1084. ATOI    PROC    NEAR
  1085.     xor    bx,bx        ; high order of this stays 0
  1086.     mov    tmp,bl        ; no input yet
  1087.     mov    cl,ah        ; number of chars of input
  1088.     xor    ch,ch        ; size of string
  1089.     xor    ax,ax        ; init sum
  1090.     cld
  1091. atoi0:    jcxz    atoi4        ; Fail on no input
  1092.     lodsb            ; get an input char
  1093.     dec    cx        ; count number remaining
  1094.     cmp    al,' '        ; leading space?
  1095.     je    atoi0        ; e = yes, skip it
  1096.     cmp    al,','        ; comma separator?
  1097.     je    atoi0        ; e = yes, skip it
  1098.     dec    si        ; back up source pointer for reread below
  1099.     inc    cx        ; and readjust byte counter
  1100.     xor    ax,ax        ; clear sum
  1101. atoi1:    push    ax        ; save sum
  1102.     lodsb            ; read a byte into al
  1103.     mov    bl,al        ; put it into bl
  1104.     pop    ax        ; regain sum
  1105.     cmp    bl,'9'        ; check range for '0' to '9'
  1106.     ja    atoi2        ; above '9'
  1107.     cmp    bl,'0'
  1108.     jb    atoi2        ; below '0'
  1109.     sub    bl,'0'        ; take away ascii bias
  1110.     mul    ten        ; sum * 10. dx = high, ax = low
  1111.     add    ax,bx        ; add current value
  1112.     mov    tmp,1        ; say have sum being computed
  1113.     loop    atoi1
  1114.     inc    si        ; inc for dec below
  1115. atoi2:    dec    si        ; point at terminator
  1116.     cmp    tmp,0        ; were any digits discovered?
  1117.     je    atoi4        ; e = no, fail
  1118.     clc            ; success
  1119.     ret
  1120. atoi4:    mov    dx,offset erms25 ; Input must be numeric
  1121.     stc            ; failure
  1122.     ret
  1123. ATOI    ENDP
  1124.  
  1125. ; Write binary number in AX as decimal asciiz to buffer pointer DI.
  1126. dec2di    proc    near        ; output number in ax using base in cx
  1127.     push    ax
  1128.     push    cx
  1129.     push    dx
  1130.     mov    cx,10
  1131.     call    dec2di1        ; recursive worker
  1132.     pop    dx
  1133.     pop    cx
  1134.     pop    ax
  1135.     ret
  1136.  
  1137. dec2di1:xor    dx,dx        ; clear high word of numerator
  1138.     div    cx        ; (ax / cx), remainder = dx, quotient = ax
  1139.     push    dx        ; save remainder for outputting later
  1140.     or    ax,ax        ; any quotient left?
  1141.     jz    dec2di2        ; z = no
  1142.     call    dec2di1        ; yes, recurse
  1143. dec2di2:pop    dx        ; get remainder
  1144.     add    dl,'0'        ; make digit printable
  1145.     mov    [di],dl        ; store char in buffer
  1146.     inc    di
  1147.     mov    byte ptr[di],0    ; add terminator
  1148.     ret
  1149. dec2di    endp
  1150.  
  1151.  
  1152. ; OPEN { READ | WRITE | APPEND } filespec
  1153. vfopen    proc    near
  1154.     mov    ah,cmkey        ; get READ/WRITE/APPEND keyword
  1155.     mov    dx,offset opntab    ; keyword table
  1156.     xor    bx,bx            ; help
  1157.     call    comnd
  1158.     jc    vfopen1            ; c = failed
  1159.     mov    temp,bx
  1160.     mov    ah,cmword        ; read filespec
  1161.     mov    dx,offset rdbuf        ; buffer for filename
  1162.     mov    bx,offset vfophlp    ; help
  1163.     call    comnd
  1164.     jc    vfopen1            ; c = failed
  1165.     mov    ah,cmeol        ; get end of line confirmation
  1166.     call    comnd
  1167.     jnc    vfopen2
  1168.     mov    kstatus,ksgen        ; general cmd failure status
  1169. vfopen1:ret                ; error return, carry set
  1170.  
  1171. vfopen2:mov    kstatus,kssuc        ; assume success status
  1172.     mov    dx,offset rdbuf        ; filename, asiiz
  1173.     mov    bx,temp            ; kind of open
  1174.     cmp    bx,1            ; open for reading?
  1175.     jne    vfopen4            ; ne = no
  1176.                     ; OPEN READ
  1177.     cmp    vfrhandle,0        ; is it open now?
  1178.     jge    vfopen8            ; ge = yes, complain
  1179.     mov    ah,open2        ; file open
  1180.     xor    al,al            ; 0 = open readonly
  1181.     cmp    dosnum,300h        ; at or above DOS 3?
  1182.     jb    vfopen3            ; b = no, so no shared access
  1183.     or    al,40h            ; open readonly, deny none
  1184. vfopen3:int    dos
  1185.     jc    vfopen9            ; c = failed to open the file
  1186.     mov    vfrhandle,ax        ; save file handle
  1187.     clc
  1188.     ret
  1189.                     ; OPEN WRITE or APPEND
  1190. vfopen4:cmp    vfwhandle,0        ; is it open now?
  1191.     jge    vfopen8            ; ge = yes, complain
  1192.     mov    ax,dx            ; filename for isfile
  1193.     call    isfile        ; check for read-only/system/vol-label/dir
  1194.     jc    vfopen7            ; c = file does not exist
  1195.     test    byte ptr filtst.dta+21,1fh    ; the no-no file attributes
  1196.     jnz    vfopen9            ; nz = do not write over one of these
  1197. vfopen5:test    filtst.fstat,80h    ; access problem?
  1198.     jnz    vfopen9            ; nz = yes, quit here
  1199.     test    byte ptr filtst.dta+21,1bh    ; r/o, hidden, volume label?
  1200.     jnz    vfopen9            ; we won't touch these
  1201.     mov    ah,open2           ; open existing file (usually a device)
  1202.     mov    al,1+1            ; open for writing
  1203.     int    dos
  1204.     jc    vfopen9            ; carry set means can't open
  1205.     mov    vfwhandle,ax        ; remember file handle
  1206.     mov    bx,ax            ; file handle for lseek
  1207.     xor    cx,cx
  1208.     xor    dx,dx            ; cx:dx = displacment
  1209.     xor    al,al            ; 0 means from start of file
  1210.     cmp    temp,2            ; WRITE? means from start of file
  1211.     je    vfopen6            ; e = yes, else APPEND
  1212.     mov    al,2            ; move to eof
  1213. vfopen6:mov    ah,lseek        ; seek the place
  1214.     int    dos
  1215.     clc
  1216.     ret
  1217.  
  1218. vfopen7:cmp    temp,1            ; READ?
  1219.     je    vfopen9            ; e = yes, should not be here
  1220.     mov    ah,creat2        ; create file
  1221.     xor    cx,cx            ; 0 = attributes bits
  1222.     int    dos
  1223.     jc    vfopen9            ; c = failed
  1224.     mov    vfwhandle,ax        ; save file handle
  1225.     clc                ; carry clear for success
  1226.     ret
  1227.  
  1228. vfopen8:mov    dx,offset vfoptwice    ; trying to reopen a file
  1229.     mov    ah,prstr
  1230.     int    dos
  1231.     mov    kstatus,kstake        ; Take file failure status
  1232.     stc
  1233.     ret
  1234. vfopen9:mov    dx,offset vfopbad    ; can't open, complain
  1235.     mov    ah,prstr
  1236.     int    dos
  1237.     mov    dx,offset rdbuf        ; filename
  1238.     call    prtasz
  1239.     mov    kstatus,kstake        ; Take file failure status
  1240.     stc
  1241.     ret
  1242. vfopen    endp
  1243.  
  1244. ; CLOSE {READ-FILE | WRITE-FILE}
  1245. vfclose    proc    near
  1246.     mov    tmp,al            ; remember kind (1=READ, 2=WRITE)
  1247.     mov    bx,vfrhandle        ; READ FILE handle
  1248.     cmp    al,1            ; READ-FILE?
  1249.     je    vfclos1            ; e = yes
  1250.     cmp    al,2            ; WRITE-FILE?
  1251.     jne    vfclos3            ; ne = no, a mistake
  1252.     mov    bx,vfwhandle        ; write handle
  1253.     or    bx,bx
  1254.     jl    vfclos3            ; l = invalid handle
  1255.     mov    dx,offset rdbuf
  1256.     xor    cx,cx            ; zero length
  1257.     push    bx            ; save handle
  1258.     mov    ah,write2        ; set file high water mark
  1259.     int    dos
  1260.     pop    bx
  1261. vfclos1:or    bx,bx
  1262.     jl    vfclos3            ; l = invalid handle
  1263.     mov    kstatus,kssuc        ; success status thus far
  1264.     mov    ah,close2        ; close file
  1265.     int    dos
  1266.     jc    vfclos4            ; c = error
  1267.     cmp    tmp,1            ; READ?
  1268.     jne    vfclos2            ; ne = no, WRITE
  1269.     mov    vfrhandle,-1        ; declare READ handle to be invalid
  1270.     clc
  1271.     ret
  1272. vfclos2:mov    vfwhandle,-1        ; declare WRITE handle to be invalid
  1273.     clc
  1274.     ret
  1275. vfclos4:mov    ah,prstr
  1276.     mov    dx,offset vfclbad    ; complain
  1277.     int    dos
  1278. vfclos3:mov    kstatus,ksgen        ; general cmd failure status
  1279.     stc
  1280.     ret
  1281. vfclose    endp
  1282.  
  1283. ; READ-FILE variable name
  1284. vfread    proc    near
  1285.     mov    comand.cmper,1        ; do not react to '\%' in macro name
  1286.     mov    ah,cmword
  1287.     mov    dx,offset rdbuf+2    ; buffer for macro name
  1288.     mov    word ptr rdbuf,0
  1289.     mov    bx,offset vfrdmsg
  1290.     call    comnd            ; get macro name
  1291.     jnc    vfread1            ; nc = success
  1292.     mov    kstatus,ksgen        ; general cmd failure status
  1293.     ret                ; failure
  1294. vfread1:or    ax,ax            ; null entry?
  1295.     jnz    vfread2            ; nz = no
  1296.     mov    dx,offset vfrdbad    ; more parameters needed
  1297.     mov    ah,prstr
  1298.     int    dos
  1299.     mov    kstatus,ksgen        ; general cmd failure status
  1300.     stc
  1301.     ret
  1302.  
  1303. vfread2:push    ax
  1304.     mov    ah,cmeol        ; get command confirmation
  1305.     call    comnd
  1306.     pop    ax            ; ax is variable length
  1307.     jc    vfreadx            ; c = failed
  1308.     mov    cx,cmdblen        ; length of rdbuf
  1309.     sub    cx,ax            ; minus macro name
  1310.     dec    cx            ; minus space separator
  1311.     mov    temp,0            ; leading whitespace and comment flgs
  1312.     mov    di,offset rdbuf+2    ; destination buffer
  1313.     add    di,ax            ; plus variable name
  1314.     mov    byte ptr [di],' '    ; space separator
  1315.     inc    di            ; put definition here
  1316.     mov    bx,vfrhandle        ; READ FILE handle
  1317.     or    bx,bx            ; check for valid handle
  1318.     jge    vfread3            ; ge = valid
  1319.     mov    ah,prstr
  1320.     mov    dx,offset vfnofile    ; say no file
  1321.     int    dos
  1322. vfreadx:mov    kstatus,ksgen        ; general cmd failure status
  1323.     stc                ; failure return
  1324.     ret
  1325. vfread3:push    cx            ; read from file
  1326.     mov    kstatus,kssuc        ; assume success status
  1327.     mov    cx,1            ; read 1 char
  1328.     mov    dx,di            ; place here
  1329.     mov    byte ptr [di],0        ; insert terminator
  1330.     mov    ah,readf2
  1331.     int    dos
  1332.     pop    cx
  1333.     jc    vfreadx            ; c = read failure
  1334.     or    ax,ax            ; count of bytes read
  1335.     jz    vfread9            ; z means end of file
  1336.     mov    al,[di]            ; get the character
  1337.     cmp    flags.takflg,0        ; echo Take files?
  1338.     je    vfread3a        ; e = no
  1339.     push    ax
  1340.     mov    ah,conout
  1341.     mov    dl,al            ; echo character
  1342.     int    dos
  1343.     pop    ax
  1344. vfread3a:cmp    al,CR            ; CR?
  1345.     je    vfread7            ; e = yes, ignore it
  1346.     cmp    al,LF            ; LF?
  1347.     je    vfread8            ; e = yes, exit
  1348.     cmp    al,';'            ; start of comment?
  1349.     jne    vfread4            ; ne = no
  1350.     mov    byte ptr temp+1,1    ; say comment has started
  1351. vfread4:cmp    byte ptr temp+1,0    ; seen comment semicolon yet?
  1352.     jne    vfread7            ; ne = yes, do not store comment
  1353.     cmp    byte ptr temp,0        ; seen non-spacing char yet?
  1354.     jne    vfread6            ; ne = yes
  1355.     cmp    al,' '            ; is this a space?
  1356.     je    vfread7            ; e = yes, skip it
  1357.     cmp    al,TAB            ; or a tab?
  1358.     je    vfread7            ; e = yes, skip it
  1359.     mov    byte ptr temp,1        ; say have seen non-spacing char
  1360.  
  1361. vfread6:inc    di            ; next storage cell
  1362. vfread7:loop    vfread3            ; loop til end of line
  1363.  
  1364. vfread8:cmp    byte ptr [di-1],'-'    ; last printable is line-continuation?
  1365.     jne    vfread10        ; ne = no, use this line as-is
  1366.     dec    di            ; point to hyphen
  1367.     mov    cx,offset rdbuf+cmdblen    ; end of rdbuf
  1368.     sub    cx,di            ; minus where we are now
  1369.     jle    vfread10        ; le = no space remaining
  1370.     mov    temp,0            ; leading whitespace and comment flgs
  1371.     jmp    vfread3            ; read another line
  1372.  
  1373. vfread9:mov    kstatus,ksgen        ; EOF, general command failure status
  1374.  
  1375. vfread10:cmp    flags.takflg,0        ; echo Take files?
  1376.     je    vfread11        ; e = no
  1377.     mov    ah,prstr
  1378.     mov    dx,offset crlf        ; for last displayed line
  1379.     int    dos
  1380.  
  1381. vfread11:mov    byte ptr [di],0        ; insert final terminator
  1382.     mov    dx,offset rdbuf+2    ; start counting from here
  1383.     push    kstatus            ; preserve status from above work
  1384.     call    strlen            ; cx becomes length
  1385.     call    dodecom            ; create the variable
  1386.     pop    kstatus            ; recover reading status
  1387.     jc    vfread12        ; c = failure
  1388.     ret
  1389. vfread12:mov    kstatus,ksgen        ; general command failure status
  1390.     mov    ah,prstr
  1391.     mov    dx,offset vfrbad    ; say error while reading
  1392.     int    dos
  1393.     stc
  1394.     ret
  1395. vfread    endp
  1396.  
  1397. ; WRITE {FILE or log} text
  1398. Write    proc    near
  1399.     mov    ah,cmkey        ; get kind of log file
  1400.     mov    dx,offset writetab    ; table of possibilities
  1401.     xor    bx,bx            ; help, when we get there
  1402.     call    comnd
  1403.     jnc    write1            ; nc = success
  1404.     mov    kstatus,ksgen        ; general cmd failure status
  1405.     ret
  1406. write1:    mov    temp,bx            ; save log file kind
  1407.     mov    ah,cmline        ; get string to be written
  1408.     mov    bx,offset rdbuf        ; where to put text
  1409.     mov    dx,offset msgtxt    ; help
  1410.     call    comnd
  1411.     mov    ah,cmeol
  1412.     call    comnd
  1413.     jnc    wpkt0
  1414.     mov    kstatus,ksgen        ; general cmd failure status
  1415.     ret                ; c = failure
  1416. wpkt0:    mov    kstatus,kssuc        ; success status thus far
  1417.     mov    si,offset rdbuf        ; start of text in buffer
  1418.     mov    di,si            ; convert in-place, to asciiz
  1419.     call    cnvlin
  1420.     mov    bx,temp            ; log file kind
  1421.     mov    si,offset rdbuf
  1422.     mov    dx,si
  1423.     call    strlen
  1424.     jcxz    wpkt2            ; z = no chars to write
  1425.     cmp    bx,logpkt        ; Packet log?
  1426.     jne    wses1            ; ne = no
  1427. wpkt1:    lodsb                ; get byte to al
  1428.     call    pktcpt            ; write to packet log
  1429.     loop    wpkt1
  1430. wpkt2:    clc                ; say success
  1431.     ret
  1432.  
  1433. wses1:    cmp    bx,logses        ; Session log?
  1434.     jne    wtrn1            ; ne = no
  1435. wses2:    lodsb                ; get byte to al
  1436.     call    cptchr            ; write to log
  1437.     loop    wses2            ; do cx chars
  1438.     clc                ; say success
  1439.     ret
  1440.  
  1441. wtrn1:    cmp    bx,logtrn        ; Transaction log?
  1442.     jne    wtrn2            ; ne = no
  1443.     mov    bx,tloghnd        ; file handle
  1444.     jmp    short wtrn4
  1445.  
  1446. wtrn2:    cmp    bx,80h            ; WRITE SCREEN?
  1447.     jne    wtrn3            ; ne = no
  1448.     xor    bx,bx            ; handle is stdout
  1449.     jmp    short wtrn4
  1450.  
  1451. wtrn3:    cmp    bx,4002h        ; WRITE FILE?
  1452.     jne    wtrn5            ; ne = no, forget this
  1453.     mov    bx,vfwhandle        ; handle
  1454.  
  1455. wtrn4:    or    bx,bx            ; is handle valid?
  1456.     jl    wtrn5            ; l = no
  1457.     mov    ah,write2        ; write to file handle in bx
  1458.     int    dos
  1459.     jc    wtrn4a            ; c = failure
  1460.     ret
  1461. wtrn4a:    mov    ah,prstr
  1462.     mov    dx,offset vfwbad    ; say error while writing
  1463.     int    dos
  1464.     mov    kstatus,ksgen
  1465.     stc
  1466.     ret
  1467. wtrn5:    mov    kstatus,ksgen        ; general cmd failure status
  1468.     mov    ah,prstr
  1469.     mov    dx,offset vfnofile    ; say no file
  1470.     int    dos
  1471.     stc
  1472.     ret
  1473. write    endp
  1474. code    ends 
  1475.     end
  1476.